﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RestSharp;
using System.Text.RegularExpressions;
using RestSharp.Deserializers;

namespace Openapi.Weibo.Api
{
    public class RestApi:RestClient
    {
        /// <summary>
        /// RestApi 默认使用BaseUrl构造
        /// </summary>
        internal RestApi()
            : base(Globals.ApiBaseUrl)
        {
            this.UserAgent = "Openapi.Weibo";
            base.AddHandler("text/plain", new JsonDeserializer());
        }

        internal RestApi(string baseUrl)
            : base(baseUrl)
        {
        }

        public IResponseResult<T> SafeExecute<T>(IRestRequest request) where T : new()
        {
            var raw = Execute(request);
            return Deserialize<T>(request,raw);
        }

        public RestRequestAsyncHandle SafeExecuteAsync<T>(IRestRequest request, Action<IResponseResult<T>, RestRequestAsyncHandle> callback)
        {
            return ExecuteAsync(request, (response, asyncHandle) =>
            {
                IResponseResult<T> restResponse = response as IResponseResult<T>;
                if (response.ResponseStatus != ResponseStatus.Aborted)
                {
                    restResponse = Deserialize<T>(request, response);
                }

                callback(restResponse, asyncHandle);
            });
        }

        private IResponseResult<T> Deserialize<T>(IRestRequest request, IRestResponse raw)
        {
            request.OnBeforeDeserialization(raw);
            ResponseResult<T> response = new ResponseResult<T>(raw);
            string pattern = @"{""request"":""(?<request>.{0,32})"",""error_code"":""(?<error_code>\d+)"",""error"":""(?<error>.{0,32})""}";
            if (Regex.IsMatch(raw.Content, pattern))
            {
                var group = Regex.Match(raw.Content, pattern);
                response.IsReturnError = true;
                response.SuccessData = default(T);
                response.ErrorData = new ResponseError
                {
                    request = group.Groups["request"].Value,
                    error_code = Int32.Parse(group.Groups["error_code"].Value),
                    error = group.Groups["error"].Value
                };
            }
            else
            {
                IDeserializer handler = GetHandler(raw.ContentType);
                handler.RootElement = request.RootElement;
                handler.DateFormat = request.DateFormat;
                handler.Namespace = request.XmlNamespace;
                try
                {
                    response.IsReturnError = false;
                    response.ErrorData = null;
                    response.SuccessData = handler.Deserialize<T>(raw);
                    //response.Request = request;
                }
                catch (Exception ex)
                {
                    response.ResponseStatus = ResponseStatus.Error;
                    response.ErrorMessage = ex.Message;
                    response.ErrorException = ex;
                }
            }
            return response;
        }

        private IDeserializer GetHandler(string contentType)
        {
            var semicolonIndex = contentType.IndexOf(';');
            if (semicolonIndex > -1)
                contentType = contentType.Substring(0, semicolonIndex);

            switch (contentType)
            {
                case "application/json":
                case "text/json":
                case "text/x-json":
                case "text/js":
                case "text/javascript":
                case "text/plain":
                    return new JsonDeserializer();
                case "application/xml":
                case "text/xml":
                default:
                    return new XmlDeserializer();
            }
        }

    }
}
